/*
 *
 *  * Unidata Platform
 *  * Copyright (c) 2013-2020, UNIDATA LLC, All rights reserved.
 *  *
 *  * Commercial License
 *  * This version of Unidata Platform is licensed commercially and is the appropriate option for the vast majority of use cases.
 *  *
 *  * Please see the Unidata Licensing page at: https://unidata-platform.com/license/
 *  * For clarification or additional options, please contact: info@unidata-platform.com
 *  * -------
 *  * Disclaimer:
 *  * -------
 *  * THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND
 *  * REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
 *  * IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY,
 *  * FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE AND
 *  * THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING.
 *
 */
package org.unidata.mdm.rest.v1.dq.core.converter;

import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Objects;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.unidata.mdm.core.util.SecurityUtils;
import org.unidata.mdm.dq.core.type.model.source.rule.EnrichmentSettings;
import org.unidata.mdm.dq.core.type.model.source.rule.QualityRuleSource;
import org.unidata.mdm.dq.core.type.model.source.rule.SelectionSettings;
import org.unidata.mdm.dq.core.type.model.source.rule.ValidationSettings;
import org.unidata.mdm.dq.core.type.rule.QualityRuleRunCondition;
import org.unidata.mdm.dq.core.type.rule.SeverityIndicator;
import org.unidata.mdm.rest.core.converter.CustomPropertiesConverter;
import org.unidata.mdm.rest.system.converter.Converter;
import org.unidata.mdm.rest.v1.dq.core.ro.rule.EnrichmentSettingsRO;
import org.unidata.mdm.rest.v1.dq.core.ro.rule.QualityRuleRO;
import org.unidata.mdm.rest.v1.dq.core.ro.rule.SelectionSettingsRO;
import org.unidata.mdm.rest.v1.dq.core.ro.rule.ValidationSettingsRO;


/**
 * The Class DQRuleDefinitionToDQRuleDefConverter.
 *
 * @author Michael Yashin. Created on 11.06.2015.
 */
public class QualityRuleConverter extends Converter<QualityRuleSource, QualityRuleRO> {

    public QualityRuleConverter() {
        super(QualityRuleConverter::convert, QualityRuleConverter::convert);
    }
    /**
     * Convert.
     *
     * @param source
     *            the source
     * @return the DQ rule definition
     */
    private static QualityRuleRO convert(QualityRuleSource source) {

        QualityRuleRO target = new QualityRuleRO();

        // Common boilerplate
        target.setName(source.getName());
        target.setDisplayName(source.getDisplayName());
        target.setDescription(source.getDescription());
        target.setCreateDate(source.getCreateDate());
        target.setUpdateDate(source.getUpdateDate());
        target.setCreatedBy(source.getCreatedBy());
        target.setUpdatedBy(source.getUpdatedBy());
        target.setCustomProperties(CustomPropertiesConverter.to(source.getCustomProperties()));

        // Rule
        target.setCleanseFunctionName(source.getCleanseFunctionName());
        target.setSelectionSettings(convert(source.getSelectionSettings()));
        target.setEnrichmentSettings(convert(source.getEnrichmentSettings()));
        target.setValidationSettings(convert(source.getValidationSettings()));
        target.setRunCondition(source.getRunCondition() == null ? null : source.getRunCondition().name());

        return target;
    }

    /**
     * Convert dqr origins definition.
     *
     * @param source
     *            the source
     * @return the DQR origins definition
     */
    private static SelectionSettingsRO convert(SelectionSettings source) {

        if (source == null) {
            return null;
        }

        SelectionSettingsRO target = new SelectionSettingsRO();

        target.setAll(source.isAll());
        target.setSourceSystems(CollectionUtils.isNotEmpty(source.getSourceSystems())
                ? new ArrayList<>(source.getSourceSystems())
                : Collections.emptyList());

        return target;
    }

    /**
     * Convert enrich.
     *
     * @param source
     *            the source
     * @return the DQ enrich definition
     */
    private static EnrichmentSettingsRO convert(EnrichmentSettings source) {

        if (source == null) {
            return null;
        }

        EnrichmentSettingsRO target = new EnrichmentSettingsRO();
        target.setSourceSystem(source.getSourceSystem());
        return target;
    }

    /**
     * Convert dqr raise definition.
     *
     * @param source
     *            the source
     * @param isSystem system rule or not
     * @return the DQR raise definition
     */
    private static ValidationSettingsRO convert(ValidationSettings source) {

        if (source == null) {
            return null;
        }

        ValidationSettingsRO target = new ValidationSettingsRO();
        target.setRaisePort(source.getRaisePort());
        target.setMessagePort(source.getMessagePort());
        target.setMessageText(source.getMessageText());
        target.setSeverityPort(source.getSeverityPort());
        target.setSeverityIndicator(source.getSeverityIndicator() == null
                ? SeverityIndicator.YELLOW.name()
                : source.getSeverityIndicator().name());
        target.setSeverityScore(source.getSeverityScore());
        target.setCategoryPort(source.getCategoryPort());
        target.setCategoryText(source.getCategoryText());

        return target;
    }

    /**
     * Convert.
     *
     * @param source
     *            the source
     * @return the DQ rule def
     */
    private static QualityRuleSource convert(QualityRuleRO source) {

        String user = SecurityUtils.getCurrentUserName();
        OffsetDateTime now = OffsetDateTime.now();

        return new QualityRuleSource()
                .withName(source.getName())
                .withDisplayName(source.getDisplayName())
                .withDescription(source.getDescription())
                .withCreateDate(Objects.isNull(source.getCreateDate()) ? now : source.getCreateDate())
                .withCreatedBy(StringUtils.isBlank(source.getCreatedBy()) ? user : source.getCreatedBy())
                .withUpdateDate(Objects.isNull(source.getCreateDate()) ? null : now)
                .withUpdatedBy(StringUtils.isBlank(source.getCreatedBy()) ? null : user)
                .withCustomProperties(CustomPropertiesConverter.from(source.getCustomProperties()))
                .withCleanseFunctionName(source.getCleanseFunctionName())
                .withRunCondition(source.getRunCondition() == null ? null : QualityRuleRunCondition.valueOf(source.getRunCondition()))
                .withSelectionSettings(convert(source.getSelectionSettings()))
                .withValidationSettings(convert(source.getValidationSettings()))
                .withEnrichmentSettings(convert(source.getEnrichmentSettings()));
    }

    /**
     * Convert dqr origins definition.
     *
     * @param source
     *            the source
     * @return the DQR origins def
     */
    private static SelectionSettings convert(SelectionSettingsRO source) {

        if (source == null) {
            return null;
        }

        return new SelectionSettings()
                .withAll(source.isAll())
                .withSourceSystems(source.getSourceSystems());
    }
    /**
     * Convert dqr raise definition.
     *
     * @param source
     *            the source
     * @return the DQR raise def
     */
    private static ValidationSettings convert(ValidationSettingsRO source) {

        if (source == null) {
            return null;
        }

        return new ValidationSettings()
                .withRaisePort(source.getRaisePort())
                .withMessagePort(source.getMessagePort())
                .withMessageText(source.getMessageText())
                .withSeverityPort(source.getSeverityPort())
                .withSeverityIndicator(source.getSeverityIndicator() == null ? SeverityIndicator.YELLOW : SeverityIndicator.valueOf(source.getSeverityIndicator()))
                .withSeverityScore(source.getSeverityScore())
                .withCategoryPort(source.getCategoryPort())
                .withCategoryText(source.getCategoryText());
    }
    /**
     * Convert dqr enrich definition.
     *
     * @param source
     *            the source
     * @return the DQR enrich def
     */
    private static EnrichmentSettings convert(EnrichmentSettingsRO source) {

        if (source == null) {
            return null;
        }

        return new EnrichmentSettings()
                .withSourceSystem(source.getSourceSystem());
    }
}
